/*
 * Flashlib - QB9 common Flash library
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package com.qb9.flashlib.tasks
{
	/**
	 * A task container runs one task at a time. It won't end if empty.
	 *
	 * @see TaskRunner
	 */
	public class Queue extends TaskContainer
	{
		/**
		 * Create a Queue task.
		 *
		 * <p>This constructor accepts either an array of ITask objects, or all the
		 * ITasks directly as arguments.</p>
		 */
		public function Queue(... args)
		{
			super(false, args);
		}

		/** @inheritDoc */
		public override function clone():ITask
		{
			return new Queue(cloneSubtasks());
		}

		/**
		 * @inheritDoc
		 */
		public override function start():void
		{
			if (running)
				return;
			super.start();
			startNext();
		}

		protected function startNext():void
		{
			if (currentTask)
			{
				if (!currentTask.running)
					currentTask.start();
			}
			else
			{
				dispatchEvent(new QueueEvent(QueueEvent.EMPTY));
			}

		}

		public override function add(task:ITask):void
		{
			super.add(task);

			if (running && subtasks.length == 1)
				startNext();
		}
		
		override public function remove(task:ITask):void
		{
			var wasFirst:Boolean = task === currentTask;
			super.remove(task);
			
			if (running && wasFirst)
				startNext();
		}

		/**
		 * @inheritDoc
		 */
		public override function stop():void
		{
			if (!running)
				return;
			super.stop();
			if (!empty && currentTask.running)
				currentTask.stop();
		}

		protected override function updateSubtasks(milliseconds:uint):uint
		{
			var task:ITask;
			var remaining:int=milliseconds;

			while (remaining > 0 && !empty)
			{
				task=currentTask;
				remaining-=updateSubtask(task, remaining);

				if (task == currentTask)
					break;
			}
			// remaing should never yield less than 0
			// but special tasks like AudioTask make it possible sometimes
			return calculateConsumed(milliseconds, Math.max(remaining, 0));
		}

		protected function calculateConsumed(total:uint, remaining:uint):uint
		{
			return total;
		}

		protected function get currentTask():ITask
		{
			return subtasks[0] as ITask;
		}
	}
}

